package xyz.wadewhy.basicstest.juc;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.task.TaskExecutor;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import static java.lang.Thread.sleep;

/**
 * 线程创建
 * 打断
 */
@Slf4j(topic = "c.Test")
class ThreadDemo<yyyyMMdd> {
    private static final Integer TEN = 10;
    private static int r = 0;

    public static void main(String[] args) throws InterruptedException {
//        createThread1();
//        createThread2();
//        FutureTask<Integer> task = createThread3();
        // 主线程阻塞，同步等待 task 执行完毕的结果
//        log.info("{}", task.get());
//        try {
//            closeThread();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        try {
//            closeThread1();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        daemonThread();
//        joinDemo();
//        yieldDemo();
        test2();
        log.info("主线程处理业务");
    }
//    private ThreadLocal SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy年MM月dd日");
    public static void test2() throws InterruptedException {
        Long time = System.currentTimeMillis();
        Date date = new Date();
        for (int i = 0; i < 20;i++) {
            Thread thread2 = new Thread(() -> {
//                System.out.println(DateUtils.getYYYYMMDDV2FromDate(time));
                System.out.println(DateUtils.getYYYYMMDDFromDateV2(date));
            }, "内部現場");
            thread2.start();
        }
    }

    public static void test() throws InterruptedException {
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            Thread thread = new Thread(() -> {
                for (int j = 0; j < 2000; j++) {
                    int finalJ = j;
                    Thread thread2 = new Thread(() -> {
                        log.info("i = {}, j = {}", finalI, finalJ);
                    }, "内部現場");
                    thread2.start();
                    try {
                        thread2.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
//                    log.info("i = {}, j = {}", finalI, finalJ);
                }
            }, "线程joinDemo");
            thread.start();
            thread.join();
        }
    }



    public static void test3() throws InterruptedException {
        TaskExecutor rt = new TaskExecutor() {
            @Override
            public void execute(Runnable task) {
                for (int i = 0; i < 20; i++) {
                    System.out.println(task + "i");
                }
            }
        };

    }


    /**
     * 创建线程的方式1，创建Thread对象
     * 1.start()只是让线程处于就绪状态，并没有真正的运行，只有cpu将时间片分给该线程，他才开始执行
     */
    public static void createThread1() {
        new Thread("线程1") {
            @Override
            public void run() {
                log.info("线程1处理业务");
            }
        }.start();
    }

    /**
     * 实现Runnable接口，实际上就是new Thread，可以看Thread的源码，构造函数
     * 推荐使用实现Runnable接口方式
     * 1.将线程和任务脱离，更灵活
     * 2.更容易与线程池等高级 API 配合
     */
    public static void createThread2() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                log.info("实现runnable接口....");
            }
        };
        new Thread(runnable, "线程2").start();
        //简化写法
        new Thread(() -> {
            log.info("lombok实现runnable接口....");
        }, "线程2-2").start();
    }

    /**
     * FutureTask 创建线程
     *
     * @return FutureTask
     * FutureTask 能够接收 Callable 类型的参数，用来处理有返回结果的情况
     */
    @SneakyThrows
    public static FutureTask<Integer> createThread3() {
        //创建任务对象
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            log.info("futureTask创建任务");
            return 200;
        });
        Thread thread = new Thread(futureTask, "futureTask任务线程");
        thread.start();
        TimeUnit.SECONDS.sleep(2);
        return futureTask;
    }

    /**
     * interrupt停止线程
     * 打断正在运行的线程，打断状态不会被清空
     */
    public static void closeThread1() throws InterruptedException {
        Thread thread = new Thread("interrupt线程") {
            @Override
            public void run() {
                while (true) {
                    Thread current = Thread.currentThread();
                    boolean interrupted = current.isInterrupted();
                    if (interrupted) {
                        log.debug(" 打断状态: {}", interrupted);
                        break;
                    }
                }
            }
        };
        thread.start();
        sleep(1);
        thread.interrupt();
    }

    /**
     * interrupt停止线程
     * 打断sleep的线程，打断状态会被清空
     *
     * @throws InterruptedException
     */
    public static void closeThread2() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.setName("线程1");
        //如果放在start之前interrupt，是没效果的
//        t1.interrupt();
        t1.start();
        sleep((long) 0.5);
        //main线程打断t1
        t1.interrupt();
        log.debug(" 打断状态: {}", t1.isInterrupted());
    }

    /**
     * 守护线程
     * 默认情况下，Java 进程需要等待所有线程都运行结束，才会结束。有一种特殊的线程叫做守护线程，只要其它非守
     * 护线程运行结束了，即使守护线程的代码没有执行完，也会强制结束。
     */
    public static void daemonThread() throws InterruptedException {
        Thread thread = new Thread(() -> {
            log.debug("守护线程 线程开始运行...");
            try {
                sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("守护线程 运行结束...");
        }, "守护线程");
        //设置成守护线程
        thread.setDaemon(true);
        thread.start();
        sleep(1);
        log.debug("main 运行结束...");
    }

    /**
     * join
     */
    public static void joinDemo() throws InterruptedException {
        log.info("begin");
        Thread thread = new Thread(() -> {
            log.debug("开始");
            try {
                sleep(1000);
                log.debug("结束");
                r = 10;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }, "线程joinDemo");
        thread.start();
        //主线程等待thread执行完
        thread.join();
        log.debug("结果为:{}", r);
        log.debug("end");
    }

    /**
     * json
     *
     * @throws InterruptedException
     */
    public static void joinDemo2() throws InterruptedException {
        log.info("begin");
        Thread thread = new Thread(() -> {
            log.debug("开始");
            try {
                sleep(1000);
                log.debug("结束");
                r = 10;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }, "线程joinDemo");
        thread.start();
        //主线程等待thread执行完,最多等待500毫秒
        thread.join(500);
        log.debug("结果为:{}", r);
        log.debug("end");
    }

    /**
     * yield 让出cpu资源
     */
    public static void yieldDemo() {
        Thread thread1 = new Thread(() -> {
            int count = 0;
            for (; ; ) {
                System.out.println("---->1 " + count++);
            }
        }, "线程1");
        Thread thread2 = new Thread(() -> {
            int count = 0;
            for (; ; ) {
                //让出cpu，所以thread2打印的比较慢
                Thread.yield();
                System.err.println("               ---->2 " + count++);
            }
        }, "线程2");
        thread1.start();
        thread2.start();
    }
}

